// NOLINT(misc-include-cleaner)
#include "SGLogger.h"  // NOLINT(clang-diagnostic-error)

#include <algorithm>
#include <exception>
#include <filesystem>
#include <fstream>
#include <memory>
#include <sstream>

#include <boost/log/attributes.hpp>           // NOLINT(misc-include-cleaner)
#include <boost/log/common.hpp>               // NOLINT(misc-include-cleaner)
#include <boost/log/core.hpp>                 // NOLINT(misc-include-cleaner)
#include <boost/log/expressions.hpp>          // NOLINT(misc-include-cleaner)
#include <boost/log/expressions/keyword.hpp>  // NOLINT(misc-include-cleaner)
#include <boost/log/expressions/message.hpp>
#include <boost/log/sinks.hpp>                // NOLINT(misc-include-cleaner)
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/syslog_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/global_logger_storage.hpp>    // NOLINT(misc-include-cleaner)
#include <boost/log/sources/severity_channel_logger.hpp>  // NOLINT(misc-include-cleaner)
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/support/date_time.hpp>                // NOLINT(misc-include-cleaner)
#include <boost/log/trivial.hpp>
#include <boost/log/utility/exception_handler.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>  // NOLINT(misc-include-cleaner)
#include <boost/log/utility/setup/filter_parser.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/utility/setup/settings.hpp>  // NOLINT(misc-include-cleaner)
#include <boost/algorithm/string.hpp>               // NOLINT(misc-include-cleaner)

#include "Utility/FileSystem/SGFileSystem.h"

namespace logging = boost::log;
namespace sinks   = boost::log::sinks;
namespace src     = boost::log::sources;
namespace trivial = boost::log::trivial;

using namespace SG::Utility;

// 定义一个宏，用于在日志中添加代码位置信息（行号、文件名和函数名）
#define BOOST_LOG_LOCATION(LOGGER, LEVEL, ARG)                                                  \
    BOOST_LOG_SEV (LOGGER, boost::log::trivial::LEVEL)                                          \
        << boost::log::add_value ("Line", __LINE__) << boost::log::add_value ("File", __FILE__) \
        << boost::log::add_value ("Function", __FUNCTION__) << ARG;

namespace
{
    // 日志配置文件名称
    const std::string LOGGER_CONFIG_FILE_NAME = "sglogger.conf";  // NOLINT(misc-include-cleaner)

    // TimeStampFormatterFactory 类提供了灵活的时间戳格式化功能，允许用户在配置文件中指定时间戳的格式，从而满足不同的日志记录需求
    class TimeStampFormatterFactory
        : public boost::log::basic_formatter_factory<
              char,
              boost::posix_time::ptime>  // NOLINT(misc-include-cleaner)
                                         // 模板类，用于创建格式化器工厂。这里模板参数char表示字符类型，boost::posix_timee::ptime
                                         // 表示时间戳的类型。
    {
      public:
        formatter_type create_formatter (const boost::log::attribute_name& name,  // NOLINT(misc-include-cleaner)
                                         const args_map& args) override  // create_formatter 是一个公共成员函数，用于创建格式化器。参数 name
                                                                         // 是属性的名称，args 是一个参数映射表，包含格式化器的配置参数。
        {
            auto it = args.find ("format");
            if (it != args.end ())                                       // 通过 args.find("format")查找参数映射表中是否存在键为"format”的项
            {
                // 如果找到了"format”键，表示用户指定了时间戳的格式，使用 boost::log::expressions::format_date time
                // 创建一个格式化器，该格式化器将根据指定的格式(it->second )格式化时间戳。
                // 返回的格式化器将被用于格式化日志记录中的时间戳属性。
                return boost::log::expressions::stream                                           // NOLINT(misc-include-cleaner)
                       << boost::log::expressions::format_date_time<boost::posix_time::ptime> (  // NOLINT(misc-include-cleaner)
                              boost::log::expressions::attr<boost::posix_time::ptime> (name),    // NOLINT(misc-include-cleaner)
                              it->second);                                                       // NOLINT(misc-include-cleaner)
            }

            // 如果没有找到"format”键，表示用户没有指定时间戳的格式，使用 boost::log::expressions::attr<boost::posix_time::ptime>
            // 创建一个格式化器，该格式化器将直接输出时间戳。
            return boost::log::expressions::stream << boost::log::expressions::attr<boost::posix_time::ptime> (name);
        }
    };

    // UptimeFormatterFactory 类提供了灵活的时间间隔格式化功能，允许用户在配置文件中指定时间间隔的格式，从而满足不同的日志记录需求
    class UptimeFormatterFactory
        : public boost::log::basic_formatter_factory<char,
                                                     boost::posix_time::time_duration>  // NOLINT(misc-include-cleaner)
                                                                                        // 这里模板参数char
    // 表示字符类型，boost::posix_time::time_duration
    // 表示时间间隔的类型
    {
      public:
        formatter_type create_formatter (const boost::log::attribute_name& name, const args_map& args) override
        {
            auto it = args.find ("format");
            if (it != args.end ())
            {
                // 通过 args.find("format")查找参数映射表中是否存在键为"format”的项。如果找到了，表示用户指定了时间间隔的格式
                // 使用 boost::log::expressions::format_date_time time_duration 创建一个格式化器，该格式化器将根据指定的格式(it->second
                // )格式化时间间隔。 返回的格式化器将被用于格式化日志记录中的时间间隔属性。
                return boost::log::expressions::stream << boost::log::expressions::format_date_time<boost::posix_time::time_duration> (
                           boost::log::expressions::attr<boost::posix_time::time_duration> (name), it->second);
            }

            // 如果没有找到"format”键，表示用户没有指定时间间隔的格式，使用
            // boost::log::expressions::attr<boost::posix_time::time_duration> 创建一个格式化器，该格式化器将直接输出时间间隔。
            return boost::log::expressions::stream << boost::log::expressions::attr<boost::posix_time::time_duration> (name);
        }
    };

    // FormattedSinkBackend 类是一个抽象基类，用于定义日志记录的逻辑处理。
    class FormattedSinkBackend
        : public sinks::basic_formatted_sink_backend<char, sinks::synchronized_feeding>  // NOLINT(misc-include-cleaner)
    {
      public:
        // 日志记录逻辑处理方法
        void consume (logging::record_view const& rec, string_type const& msg)  // NOLINT(misc-include-cleaner)
        {}
    };

    using FormattedSink = sinks::synchronous_sink<FormattedSinkBackend>;

}  // namespace

// 定义了一个私有结构体 SGLoggerPrivate
// 其中包含一个多线程安全的严重性日志记录器 severity_1ogger。
// 这个日志记录器可以用于记录不同严重性级别的日志消息，并且确保在多线程环境下的安全性。
// 通过这种方式，SGLogger 类可以有效地管理和记录日志信息。
struct SGLogger::SGLoggerPrivate
{
    /// The embedded logger
    // severity_logger_mt是一个多线程安全的严重性日志记录器，它可以用于记录不同严重性级别的日志消息。
    // trivial::severity level:这是 Boost.Log
    // 库中定义的一个枚举类型，表示日志消息的严重性级别，例如trace、debug、info、warning、error和fatal。
    src::severity_logger_mt<trivial::severity_level> severity_logger;  // NOLINT(misc-include-cleaner)
};

// 静态成员初始化
std::string SGLogger::s_workspace;

// 初始化日志记录器
SGLogger::SGLogger ()
{
    imp = std::make_shared<SGLoggerPrivate> ();
    // 配置文件路径
    const std::string path = SG::Utility::FileSystem::getCurrentExecutablePath ();
    init (path + "/" + LOGGER_CONFIG_FILE_NAME);
}

SGLogger& SGLogger::get ()
{
    static SGLogger logger;
    return logger;
}
// 便捷初始化：使用默认配置文件名并设置工作空间
void SGLogger::initWithWorkspace (const std::string& workspace)
{
    const std::string exePath = SG::Utility::FileSystem::getCurrentExecutablePath ();
    SGLogger::init (exePath + "/" + LOGGER_CONFIG_FILE_NAME, workspace);
}

// 使用默认配置初始化
void SGLogger::init (const std::string& filePath)
{
    init (filePath, s_workspace);
}

// 支持传入工作空间的初始化
void SGLogger::init (const std::string& filePath, const std::string& workspace)
{
    // 保存工作空间
    s_workspace = workspace;
    // 重新初始化前清空所有已注册的 sinks，防止重复添加
    boost::log::core::get ()->remove_all_sinks ();
    // boost::log::core 类的静态成员函数 get()来获取日志系统的核心对象。这个核心对象是全局唯一的，负责管理所有的日志记录器和接收器(sink)。
    // 调用了日志核心对象的set_exception_handler方法，并传入了一个由 boost::log::make_exception_suppressor()创建的异常处理器。
    // 调用了 boost::log 库提供的 make_exception_suppressor
    // 函数，该函数返回一个异常处理器。这个异常处理器的作用是抑制所有在日志记录过程中抛出的异常，即捕获但不处理这些异常。
    boost::log::core::get ()->set_exception_handler (boost::log::make_exception_suppressor ());

    // 向日志系统中注册一些常见的属性，这些属性包括日志记录的行号、时间戳、进程ID和线程ID。
    boost::log::add_common_attributes ();

    // Add boost log timer as global attribute Uptime
    // boost::log::core 类的静态成员函数 get()来获取日志系统的核心对象。这个核心对象是全局唯一的，负责管理所有的日志记录器和接收器(sink)。
    // 调用了日志核心对象的add_global_attribute方法，并传入了名称为"Uptime"的全局属性和boost::log::attributes::timer的计时器属性。
    // 这个属性的作用是记录日志记录的运行时间。
    boost::log::core::get ()->add_global_attribute ("Uptime", boost::log::attributes::timer ());

    // register_simple_filter_factory用于注册一个简单的过滤器工厂。过滤器工厂用于创建过滤器，这些过滤器可以根据某些条件(如日志级别)来决定是否记录某个日志记录。
    // 这里注册了一个名为"Severity"的简单过滤器工厂，该工厂可以根据日志消息的严重性级别来过滤日志记录。
    boost::log::register_simple_filter_factory<boost::log::trivial::severity_level, char> ("Severity");

    // register_simple_formatter_factory用于注册一个简单的格式化器工厂。格式化器工厂用于创建格式化器，这些格式化器可以根据日志消息的属性来格式化日志记录。
    // 这里注册了一个名为"Severity"的简单格式化器工厂，该工厂可以根据日志消息的严重性级别来格式化日志记录。
    boost::log::register_simple_formatter_factory<boost::log::trivial::severity_level, char> ("Severity");

    // register_formatter_factory用于注册一个格式化器工厂。格式化器工厂用于创建格式化器，这些格式化器可以根据日志消息的属性来格式化日志记录。
    // 这里注册了一个名为"TimeStamp"的格式化器工厂，该工厂可以根据日志消息的时间戳来格式化日志记录。
    boost::log::register_formatter_factory ("TimeStamp", boost::make_shared<TimeStampFormatterFactory> ());  // NOLINT(misc-include-cleaner)

    // register_formatter_factory用于注册一个格式化器工厂。格式化器工厂用于创建格式化器，这些格式化器可以根据日志消息的属性来格式化日志记录。
    // 这里注册了一个名为"Uptime"的格式化器工厂，该工厂可以根据日志消息的运行时间来格式化日志记录。
    boost::log::register_formatter_factory ("Uptime", boost::make_shared<UptimeFormatterFactory> ());

    // 检查filePath是否为空，如果为空，则表示用户没有指定日志配置文件，则默认输出到控制台。
    if (!filePath.empty ())
    {
        // Make sure we log to console if nothing specified.
        // Severity logger logs to console by default.
        // 读取配置文件并进行 ${WORKSPACE} 占位符替换
        std::ifstream ifs (filePath);
        // 判断文件是否可以打开
        if (!ifs.is_open ())
        {
            // 如果文件无法打开，则输出一条警告信息
            BOOST_LOG_TRIVIAL (warning) << "Unable to open logging config file: " << filePath << ". Using default console logging." << '\n';

            // 创建默认的日志接收器
            addTextFileSink ();
            addConsoleSink ();
            // throw std::runtime_error ("Unable to open logging config file: " + filePath);
        }
        else
        {
            try
            {
                // 将文件内容读取到字符串中
                const std::string content ((std::istreambuf_iterator<char> (ifs)), std::istreambuf_iterator<char> ());
                ifs.close ();

                std::string to_parse = content;
                if (!s_workspace.empty ())
                {
                    // 将路径中的反斜杠替换为正斜杠，避免转义问题
                    std::string normalized_workspace = s_workspace;
                    boost::replace_all (normalized_workspace, "\\", "/");
                    boost::replace_all (to_parse, "%workspace%", normalized_workspace);
                }

                // 使用 stringstream 喂给 Boost.Log 解析器
                std::istringstream iss (to_parse);
                boost::log::init_from_stream (iss);
            }
            catch (std::exception& e)
            {
                std::string err = "Caught exception initializing boost logging: ";
                err += e.what ();
                // Since we cannot be sure of boost log state, output to cerr and cout.
                // 将异常信息输出到 cerr 和 cout
                std::cerr << "ERROR: " << err << '\n';  // NOLINT(misc-include-cleaner)
                std::cout << "ERROR: " << err << '\n';  // NOLINT(misc-include-cleaner)
                BOOST_LOG_TRIVIAL (warning) << err;
            }
        }
    }

    // BOOST_LOG_TRIVIAL (info) << "Log Start";
}

void SGLogger::createDefaultSink ()
{
    // 创建格式化的日志接收器
    boost::shared_ptr<FormattedSink> const formatted_sink = boost::make_shared<FormattedSink> ();  // NOLINT(misc-include-cleaner)

    // 设置日志输出的格式化器
    formatted_sink->set_formatter (
        // %1%对应时间戳，使用boost::log::expressions::attr<boost::posix time::ptime>("Timestamp")获取。
        // %2%对应严重性级别，使用 boost::log::trivial::severity 获取。
        // %3%对应日志消息，使用 boost::log::expressions::smessage 获取。
        boost::log::expressions::format ("[%1%][%2%] %3%")
        % boost::log::expressions::attr<boost::posix_time::ptime> ("TimeStamp")  // NOLINT(misc-include-cleaner)
        % boost::log::trivial::severity % boost::log::expressions::smessage);    // NOLINT(misc-include-cleaner)

    // 设置日志过滤器，只记录严重性级别大于等于info的日志
    formatted_sink->set_filter (boost::log::trivial::severity >= boost::log::trivial::info);

    // 将格式化的日志接收器注册到日志系统中
    boost::log::core::get ()->add_sink (formatted_sink);
}

// 禁用日志系统
void SGLogger::disable ()
{
    boost::log::core::get ()->set_logging_enabled (false);
}

void SGLogger::addTextFileSink (const std::string& filePath)
{
    // 创建一个文本文件日志接收器
    // #if 0
    //     typedef sinks::synchronous_sink< sinks::text_ostream_backend > text_sink;
    //     boost::shared_ptr< text_sink > sink = boost::make_shared< text_sink >();

    //     // Add a stream to write log to
    //     sink->locked_backend()->add_stream(
    //         boost::make_shared< std::ofstream >(filePath));
    // #else
    // sinks::synchronous_sink 是一个同步的日志接收器
    // sinks::text_file_backend 是一个文本文件后端，用于将日志写入文件
    using text_sink = sinks::synchronous_sink<sinks::text_file_backend>;  // NOLINT(misc-include-cleaner)

    // 创建一个文本文件日志接收器
    boost::shared_ptr<text_sink> const sink = boost::make_shared<text_sink> ();

    // 调用 sink的 locked_backend 方法，获取后端并设置文件名模式为传入的 filePath
    sink->locked_backend ()->set_file_name_pattern (filePath);

    // 设置日志文件的打开模式为追加(std::ios_base::app)和输出(std::ios_base::out)
    sink->locked_backend ()->set_open_mode (std::ios_base::app | std::ios_base::out);  // NOLINT(misc-include-cleaner)

    // 设置日志文件的轮换大小为 4MB(4*1024*1024字节)。当日志文件达到这个大小后，会自动创建一个新的日志文件。
    sink->locked_backend ()->set_rotation_size (4L * 1024L * 1024L);
    // #endif
    //  locked_backend
    //  锁定接收器的后端，以确保在多线程环境中对后端的访问是安全的。锁定后端可以防止多个线程同时修改后端的状态，从而避免数据竞争和不一致的问题。
    //  auto_flush 是一个方法，用于设置是否自动刷新日志缓冲区。当设置为 true
    //  时，每次写入日志记录后都会自动刷新缓冲区，确保日志记录立即写入到目标(例如文件)中。当设置为 false
    //  时，日志记录可能会在缓区中积累，直到缓冲区满或显式调用刷新操作。
    sink->locked_backend ()->auto_flush (true);

    // 设置日志输出的格式化器
    sink->set_formatter (
        // %1%对应时间戳，使用boost::log::expressions::attr<boost::posix time::ptime>("Timestamp")获取。
        // %2%对应严重性级别，使用 boost::log::trivial::severity 获取。
        // %3%对应日志消息，使用 boost::log::expressions::smessage 获取。
        boost::log::expressions::format ("[%1%][%2%] %3%") % boost::log::expressions::attr<boost::posix_time::ptime> ("TimeStamp")
        % boost::log::trivial::severity % boost::log::expressions::smessage);

    // 设置日志过滤器，只记录严重性级别大于等于info的日志
    sink->set_filter (boost::log::trivial::severity >= boost::log::trivial::info);

    boost::log::core::get ()->add_sink (sink);
}

void SGLogger::addTextFileSink ()
{
    // sinks::synchronous_sink 是一个同步的日志接收器
    // sinks::text_file_backend 是一个文本文件后端，用于将日志写入文件
    using text_sink = sinks::synchronous_sink<sinks::text_file_backend>;

    // 创建一个文本文件日志接收器
    boost::shared_ptr<text_sink> const sink = boost::make_shared<text_sink> ();

    // 调用 sink的 locked_backend 方法，获取后端并设置文件名模式为传入的 filePath
    // 默认文件名模式；优先写入到工作空间下的 logs 目录
    std::string filePattern = "log_%N.log";
    if (!s_workspace.empty ())
    {
        const std::filesystem::path target = std::filesystem::path (s_workspace) / "logs";
        std::error_code             ec;
        std::filesystem::create_directories (target, ec);  // 忽略失败
        filePattern = (target / filePattern).string ();
    }
    sink->locked_backend ()->set_file_name_pattern (filePattern);

    // 设置日志文件的打开模式为追加(std::ios_base::app)和输出(std::ios_base::out)
    sink->locked_backend ()->set_open_mode (std::ios_base::app | std::ios_base::out);

    // 设置日志文件的轮换大小为 4MB(4*1024*1024字节)。当日志文件达到这个大小后，会自动创建一个新的日志文件。
    sink->locked_backend ()->set_rotation_size (4L * 1024 * 1024);

    // locked_backend
    // 锁定接收器的后端，以确保在多线程环境中对后端的访问是安全的。锁定后端可以防止多个线程同时修改后端的状态，从而避免数据竞争和不一致的问题。
    // auto_flush 是一个方法，用于设置是否自动刷新日志缓冲区。当设置为 true
    // 时，每次写入日志记录后都会自动刷新缓冲区，确保日志记录立即写入到目标(例如文件)中。当设置为 false
    // 时，日志记录可能会在缓区中积累，直到缓冲区满或显式调用刷新操作。
    sink->locked_backend ()->auto_flush (true);

    // sink->locked_backend()->set_target_file_name_pattern("./logs");

    // 设置日志输出的格式化器
    sink->set_formatter (
        // %1%对应时间戳，使用boost::log::expressions::attr<boost::posix time::ptime>("Timestamp")获取。
        // %2%对应严重性级别，使用 boost::log::trivial::severity 获取。
        // %3%对应日志消息，使用 boost::log::expressions::smessage 获取。
        boost::log::expressions::format ("[%1%][%2%] %3%") % boost::log::expressions::attr<boost::posix_time::ptime> ("TimeStamp")
        % boost::log::trivial::severity % boost::log::expressions::smessage);

    // 设置日志过滤器，只记录严重性级别大于等于info的日志
    sink->set_filter (boost::log::trivial::severity >= boost::log::trivial::trace);

    boost::log::core::get ()->add_sink (sink);
}

void SGLogger::addConsoleSink ()
{
    // sinks::synchronous_sink 是一个同步的日志接收器
    // sinks::text_file_backend 是一个文本文件后端，用于将日志写入文件
    using text_sink = sinks::synchronous_sink<sinks::text_ostream_backend>;

    // 创建一个文本文件日志接收器
    boost::shared_ptr<text_sink> const sink = boost::make_shared<text_sink> ();

    boost::shared_ptr<std::ostream> const stream (&std::clog, boost::null_deleter ());  // NOLINT(misc-include-cleaner)
    sink->locked_backend ()->add_stream (stream);

    // locked_backend
    // 锁定接收器的后端，以确保在多线程环境中对后端的访问是安全的。锁定后端可以防止多个线程同时修改后端的状态，从而避免数据竞争和不一致的问题。
    // auto_flush 是一个方法，用于设置是否自动刷新日志缓冲区。当设置为 true
    // 时，每次写入日志记录后都会自动刷新缓冲区，确保日志记录立即写入到目标(例如文件)中。当设置为 false
    // 时，日志记录可能会在缓区中积累，直到缓冲区满或显式调用刷新操作。
    sink->locked_backend ()->auto_flush (true);

    // sink->locked_backend()->set_target_file_name_pattern("./logs");

    // 设置日志输出的格式化器
    sink->set_formatter (
        // %1%对应时间戳，使用boost::log::expressions::attr<boost::posix time::ptime>("Timestamp")获取。
        // %2%对应严重性级别，使用 boost::log::trivial::severity 获取。
        // %3%对应日志消息，使用 boost::log::expressions::smessage 获取。
        boost::log::expressions::format ("[%1%][%2%] %3%") % boost::log::expressions::attr<boost::posix_time::ptime> ("TimeStamp")
        % boost::log::trivial::severity % boost::log::expressions::smessage);

    // 设置日志过滤器，只记录严重性级别大于等于info的日志
    sink->set_filter (boost::log::trivial::severity >= boost::log::trivial::trace);

    boost::log::core::get ()->add_sink (sink);
}

void SGLogger::addSyslogSink (std::string const& addr, unsigned short port)
{
    using syslog_sink                         = sinks::synchronous_sink<sinks::syslog_backend>;
    boost::shared_ptr<syslog_sink> const sink = boost::make_shared<syslog_sink> ();

    // 设置 syslog 后端的地址和端口
    sink->locked_backend ()->set_target_address (addr, port);

    // 设置日志输出的格式化器
    sink->set_formatter (boost::log::expressions::format ("[%1%][%2%] %3%")
                         % boost::log::expressions::attr<boost::posix_time::ptime> ("TimeStamp") % boost::log::trivial::severity
                         % boost::log::expressions::smessage);

    // 设置日志过滤器，只记录严重性级别大于等于info的日志
    sink->set_filter (boost::log::trivial::severity >= boost::log::trivial::info);

    // 将格式化的日志接收器注册到日志系统中
    boost::log::core::get ()->add_sink (sink);
}

// BOOST_LOG_LOCATION 用于在日志中添加代码位置信息(行号、文件名和函数名)
// 调用 BOOST_LOG_LOCATION 宏，传入日志记录器 severity_logger、日志级别和日志消息，即可记录带有代码位置信息的日志。
// severity_logger 表示一个多线程安全的严重性日志记录器
// trace 表示日志严重性级别
// msg 表示日志消息
void SGLogger::trace (const std::string& msg) const
{
    BOOST_LOG_LOCATION (imp->severity_logger, trace, msg);
}

void SGLogger::debug (const std::string& msg) const
{
    BOOST_LOG_LOCATION (imp->severity_logger, debug, msg);
}

void SGLogger::info (const std::string& msg) const
{
    BOOST_LOG_LOCATION (imp->severity_logger, info, msg);
}

void SGLogger::warning (const std::string& msg) const
{
    BOOST_LOG_LOCATION (imp->severity_logger, warning, msg);
}

void SGLogger::error (const std::string& msg) const
{
    BOOST_LOG_LOCATION (imp->severity_logger, error, msg);
}

void SGLogger::fatal (const std::string& msg) const
{
    BOOST_LOG_LOCATION (imp->severity_logger, fatal, msg);
}

SGLogRecordStream::SGLogRecordStream (const SGLogger* theLogger, SGLogLevel theLevel) : logger (theLogger), level (theLevel)
{}

SGLogRecordStream::SGLogRecordStream (const SGLogRecordStream& other)
{
    logger = other.logger;
    level  = other.level;
}

// 记录不同级别的日志消息，并在对象销毁时自动输出日志消息
SGLogRecordStream::~SGLogRecordStream ()
{
    if (nullptr == logger)
    {
        return;
    }

    switch (level)
    {
    case SGLogLevel::trace:
        logger->trace (this->str ());
        break;
    case SGLogLevel::debug:
        logger->debug (this->str ());
        break;
    case SGLogLevel::info:
        logger->info (this->str ());
        break;
    case SGLogLevel::warning:
        logger->warning (this->str ());
        break;
    case SGLogLevel::error:
        logger->error (this->str ());
        break;
    case SGLogLevel::fatal:
        logger->fatal (this->str ());
        break;
    }
}

SGLogRecordStream& SG::Utility::operator<< (SGLogRecordStream& stream, const std::vector<std::string>& values)
{
    stream << '[';
    for (std::size_t idx = 0; idx < values.size (); ++idx)
    {
        if (idx != 0)
        {
            stream << ", ";
        }
        stream << values[idx];
    }
    stream << ']';
    return stream;
}